• 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.

LCD problem

Status
Not open for further replies.

lele_75

New Member
hi,
i'm starting with lcd programming, but i can only display a black squares row...

i'm using a PIC 16F877A and a 16X2 LCD display (MDLS 16265K, 44780 compatible) with a OLIMEX P40 board (20Mhz frequency)

here the connections:

LCD PIC
RS RB1
RW RB2
EN RB0
D4 RB4
D5 RB5
D6 RB6
D7 RB7


it seems to be all ok but i'm working from 1 week and i'm not understanding where the problem is.

this is the test code:

Code:
#include <pic.h>
#include "defs.h"
#include "lcd.h"
#include "delay.h"

void main (void)
	{
	UINT	i;
	byte	j;
	const byte const UpArrow[] = {0x04, 0x0e, 0x15, 0x04, 0x04, 0x04, 0x04, 0x04};
	const byte const DownArrow[] = {0x04, 0x04, 0x04, 0x04, 0x04, 0x15, 0x0e, 0x04};

	TRISB = 0;
	PORTB = 0;
	TRISA=0;

	lcd_init ();
	
	lcd_clear ();
	lcd_command (LCD_COMMAND_HOME);				// Home cursor

	lcd_define_char (0, UpArrow);				// Define user-defined char
	lcd_define_char (1, DownArrow);				// Define user-defined char

	lcd_gotoxy (1,1);
	lcd_putc (0);
	lcd_gotoxy (2,1);
	lcd_putc (1);						// Display special character


	lcd_gotoxy (1,8);

	for (j = 0; j < 43; j++)
		{
		lcd_putc ('.');
		for (i = 0; i < 1000; i++)
			delay_mS (1);
		}


	NOP ();
	asm ("goto $-1");*/
	}

and this is lcd.c

Code:
/****************************************************************************
**									   **
**		    	Hitachi Character-Type LCD Display		   **
**									   **
****************************************************************************/
//
//		NOTE: 	This is set up for 4 MHz oscillator
//

#define	LCD_C								// "I am LCD.C"

#ifndef CLRWDT
#include <pic.h>
#endif
#include "defs.h"
#include "lcd.h"
#include "delay.h"							// Contains delay routines & macros

const byte const LCD_ROW_ADDRESS[] =					// Row/Column information for lcd_gotoxy()
	{
#if LCD_MODE_1x8
	0x00
#endif
#if LCD_MODE_1x16_A
	0x00
#endif
#if LCD_MODE_1x16_B
	0x00,
	0x40
#endif
#if LCD_MODE_1x40
	0x00,
#endif
#if LCD_MODE_2x8
	0x00,
	0x40
#endif
#if LCD_MODE_2x12
	0x00,
	0x40
#endif
#if LCD_MODE_2x16
	0x00,
	0x40
#endif
#if LCD_MODE_2x20
	0x00,
	0x40
#endif
#if LCD_MODE_2x24
	0x00,
	0x40
#endif
#if LCD_MODE_2x40
	0x00,
	0x40
#endif
#if LCD_MODE_4x16
	0x00,
	0x40,
	0x10,
	0x50
#endif
#if LCD_MODE_4x20
	0x00,
	0x40,
	0x14,
	0x54
#endif
#if LCD_MODE_4x24
	0x00,
	0x40,
	0x80,
	0xc0
#endif
	};

const byte const LCD_INIT_STRING [] =					// LCD Init String on powerup
	{
	0b00000001,							//	Clear display
	0b00000010,							//	Home cursor
	0b00000100							//	Entry Mode
#if LCD_CURSOR_INCREMENT
	| 0b00000010							//		Increment cursor
#endif
#if LCD_CURSOR_SHIFT
	| 0b00000001							//		Shift on cursor
#endif
		,							//		end
	0b00001000							//	Display Control
#if LCD_DISPLAY_ON
	| 0b00000100							//		Display on
#endif
#if LCD_CURSOR_ON
	| 0b00000010							//		Cursor on
#endif
#if LCD_CURSOR_BLINK
	| 0b00000001							//		Blink on
#endif
		,							//		end
	0b00100000							//	Function Set
#if LCD_8_BIT_MODE
	| 0b00010000							//		8-bit data bus
#endif
#if LCD_MULTI_LINE
	| 0b00001000							//		2-line refreshing
#endif
#if LCD_DISPLAY_5x10
	| 0b00000100							//		5x10 matrix
#endif
	};

#if LCD_4_BIT_MODE
void lcd_putnybble (byte c)						// Write nybble to port in current RS mode
	{
	c = c << LCD_D4_BIT;						// Shift over to correct bit column
	c &= LCD_TRIS_DATAMASK;						// Remove any extraneous bits
	LCD_DATA_PORT = (LCD_DATA_PORT & ~LCD_TRIS_DATAMASK) | c;	// Write data bits to port
	delay_uS (1);
	LCD_E = 1;							// Start to write it
	delay_uS (2);
	LCD_E = 0;							// Finish write cycle
	}
#endif

byte lcd_getbyte (void)							// Read byte at cursor (RS=1) or ready status (RS=0)
	{
	byte	retval;
#if LCD_4_BIT_MODE
	byte	highbits;

	LCD_TRIS_PORT |= LCD_TRIS_DATAMASK;				// Set port to read mode for data pins
	LCD_RW = 1;							// Tell LCD we want to read
	delay_uS (1);
	LCD_E = 1;
	highbits = (((LCD_DATA_PORT & LCD_TRIS_DATAMASK) >> LCD_D4_BIT) << 4);// Grab high bits and shift to right place
	LCD_E = 0;
	delay_uS (1);
	LCD_E = 1;
	delay_uS (1);
	retval = ((LCD_DATA_PORT & LCD_TRIS_DATAMASK) >> LCD_D4_BIT);	// Grab low bits
	LCD_E = 0;
	retval |= highbits;
	LCD_TRIS_PORT &= ~LCD_TRIS_DATAMASK;				// Set port back to output mode
#else
	LCD_TRIS_PORT = 0xFF;						// Set port to all input
	LCD_RW = 1;							// Tell LCD we want to read
	delay_uS (1);
	LCD_E = 1;							// Do the read
	delay_uS (1);
	retval = LCD_DATA_PORT;
	LCD_E = 0;
	LCD_TRIS_PORT = 0x00;						// Set port back to outputs
#endif
	return (retval);						// Give answer to caller
	}

void lcd_putbyte (byte c)						// Write byte to port in current RS mode
	{
	byte	RS_Status;

	RS_Status = LCD_RS;						// Get old pin state
	LCD_RS = 0;							// Force into command mode to read state
	while (lcd_getbyte () & 0x80);					// Wait for read state
	if (RS_Status)
		LCD_RS = 1;						// Restore RS to old state
	delay_uS (1);
	LCD_RW = 0;							// Set to write mode
	delay_uS (1);
#if LCD_4_BIT_MODE
	lcd_putnybble (c >> 4);						// Send the character out
	lcd_putnybble (c);
#else
	LCD_DATA_PORT = c;						// Send the character out
#endif
	LCD_E = 1;
	delay_uS (1);
	LCD_E = 0;
	}

void lcd_command (byte c)						// Send command to LCD port
	{
	LCD_RS = 0;
	lcd_putbyte (c);
	}

#if LCD_ALLOW_USER_CHARS
void lcd_define_char (byte c, const byte *bitmap)			// Define user-defined chars
	{
	byte	i;

	lcd_command ((0b01000000) | (c << 3));					// Select char to define

	LCD_RS = 1;
	for (i = 0; i < 8; i++)
		lcd_putbyte (*bitmap++);				//	Put in each byte of memory
	}
#endif

byte lcd_lineof (byte CursorAddress)					// Calculate cursor row from it's address
	{
	CursorAddress &= 0x50;						//	Strips out uniquely the address bits
	switch (CursorAddress)
		{
		case 0x00:						// Note - this handles all cases except for some
			CursorAddress = 1;				//	of those unsupported displays listed in
		case 0x40:						//	lcd.h file.
#if LCD_MODE_1x16_B
			CursorAddress = 1;				//	Only 1 row this type of display
#else
			CursorAddress = 2;
#endif
		case 0x10:
			CursorAddress = 3;
		case 0x50:
			CursorAddress = 4;
		default:
			CursorAddress = 1;
		}
	return (CursorAddress);
	}

byte lcd_cursorpos (void)						// Return address of cursor position
	{
	LCD_RS = 0;
	return (lcd_getbyte ());					//	Get cursor position
	}

void lcd_putc (byte c)							// Write character to LCD
	{
#if !LCD_ALLOW_USER_CHARS
	byte	CursAddr;
#endif
#if LCD_ALLOW_USER_CHARS						// Allow user-defined characters - no terminal mode
		LCD_RS = 1;
		lcd_putbyte (c);
#else
	switch (c)
		{
		case '\b':						//	Backspace?
			lcd_command (LCD_COMMAND_BACKSPACE);		//		back cursor up
#if LCD_DESTRUCTIVE_BS
			LCD_RS = 1;					//		set display mode
			lcd_putbyte (' ');				//		erase previous character
			lcd_command (LCD_COMMAND_BACKSPACE);		//		move cursor back again
#endif
			break;
		case '\n':						//	Newline?
			RS = 0;
			CursAddr = lcd_getbyte ();			//		Get cursor position
			CursAddr = lcd_lineof (CursAddr);
#if LCD_ENABLE_SCROLL
			if (CursAddr >= LCD_MAXROWS)			//		Bottom line?
				lcd_scroll ();				//			Yes, force scroll
			else						//			No, just go to start of next line
				lcd_gotoxy (CursAddr+1,1);
#else
			lcd_gotoxy (CursAddr+1, 1);			//		Position cursor to start of line
#endif
			break;
		case '\f':						//	Form Feed (clear screen)?
			lcd_command (LCD_COMMAND_CLEAR);		//		Erase screen
			lcd_gotoxy (1,1);				//		Position cursor to top of screen
			break;
		default:						//	Printable?
			LCD_RS = 1;					//		Set to display mode
			lcd_putbyte (c);				//		Send character out
		}
#endif
	}

#if LCD_ENABLE_GETC
byte lcd_getc (void)							// Read character at cursor
	{
	byte	retval;

	LCD_RS = 1;
	retval = lcd_getbyte ();
	LCD_RS = 0;
	return (retval);
	}
#endif

#if LCD_ENABLE_GOTOXY
void lcd_gotoxy (byte row, byte col)					// Position cursor
	{
#if LCD_MODE_1x16_B
	if (col > 7)							// 1x16 is treated the same as 2x8 for addressing
		{
		row++;
		col -= 8;
		}
	if (col > 8)
		col = 8;
	if (row > 2)
		row = 2;
#else
	if (row > LCD_MAXROWS)						// Range limit
		row = LCD_MAXROWS;
	if (col > LCD_MAXCOLS)
		col = LCD_MAXCOLS;
#endif

	row = LCD_ROW_ADDRESS[row-1];					// Get address of first byte on desired row
	row += col - 1;

	lcd_command (0x80 | row);					// Write new cursor address
	}

void lcd_getxy (byte *row, byte *col)					// Return row and column of cursor position
	{
	byte	rr,
		cc;

	cc = lcd_cursorpos ();
	rr = lcd_lineof (cc);						//	Get row of the cursor
	cc = (cc & 0x7f) - LCD_ROW_ADDRESS[rr-1];			//	Find the column
	*row = rr;							//	Convert to lcd_gotoxy() units
	*col = cc;
	}

#endif

#if LCD_ENABLE_PRINTF
void lcd_printf (const char* message)					// Write message to LCD (C string type)
	{
	while (*message)						//	Look for end of string
		lcd_putc (*message++);					//	Show and bump
	}
#endif

#if LCD_ENABLE_SCROLL
void lcd_scroll (void)							// Scroll up one line
	{
	byte	CursorPos,						// Hold position of cursor
		Character,						// Hold character being moved
		SrcAddr,						// Source Address
		DestAddr,						// Destination Address
		EndAddr;						// Ending copy address (last address of Source)

	LCD_RS = 0;
	CursorPos = lcd_getbyte () | 0x80;				// Get cursor position

	lcd_gotoxy (2,1);
	LCD_RS = 0;
	SrcAddr = lcd_getbyte () | 0x80;				// Find address of copy start
	lcd_gotoxy (1,1);
	LCD_RS = 0;
	DestAddr = lcd_getbyte () | 0x80;				// Find address of copy destination
	lcd_gotoxy (LCD_MAXROWS, LCD_MAXCOLS);
	LCD_RS = 0;
	EndAddr = lcd_getbyte () | 0x80;				// Find address of last byte to copy over

	do
		{
		LCD_RS = 0;						//	Position to source of copy char
		lcd_putbyte (SrcAddr);
		LCD_RS = 1;
		Character = lcd_getbyte ();				//	Read the character there
		LCD_RS = 0;
		lcd_putbyte (DestAddr);					//	Move to the destination
		LCD_RS = 1;
		lcd_putbyte (Character);				//	Write it the char there
		SrcAddr++;
		DestAddr++;
		}
	while (SrcAddr <= EndAddr);					// Loop through all memory

	for (Character = 1; Character <= LCD_MAXCOLS; Character++)
		{
		lcd_gotoxy (LCD_MAXROWS, Character);			//	Position on last line
		lcd_putc (' ');						//	Blank out the char
		}
	lcd_gotoxy (lcd_lineof (CursorPos) + 1,1);			// Home cursor next line
	}
#endif

#if LCD_ENABLE_UNSCROLL
void lcd_unscroll (void)						// Roll scroll backwards one line
	{
	byte	CursorPos,						// Hold position of cursor
		Character,						// Hold character being moved
		SrcAddr,						// Source Address
		DestAddr;						// Destination Address

	LCD_RS = 0;
	CursorPos = lcd_getbyte () | 0x80;				// Get cursor position

	lcd_gotoxy (LCD_MAXROWS-1,LCD_MAXCOLS);
	LCD_RS = 0;
	SrcAddr = lcd_getbyte () | 0x80;				// Find address of copy start

	lcd_gotoxy (LCD_MAXROWS,LCD_MAXCOLS);
	LCD_RS = 0;
	DestAddr = lcd_getbyte () | 0x80;				// Find address of copy destination

	do
		{
		LCD_RS = 0;						//	Position to source of copy char
		lcd_putbyte (SrcAddr);
		LCD_RS = 1;
		Character = lcd_getbyte ();				//	Read the character there
		LCD_RS = 0;
		lcd_putbyte (DestAddr);					//	Move to the destination
		LCD_RS = 1;
		lcd_putbyte (Character);				//	Write it the char there
		SrcAddr--;
		DestAddr--;
		}
	while (SrcAddr != 0x80);					// Loop through all memory

	for (Character = 0; Character < LCD_MAXCOLS; Character++)
		{
		lcd_gotoxy (1, Character);				//	Position on top row
		lcd_putc (' ');						//	Blank out the char
		}
	lcd_gotoxy (lcd_lineof (CursorPos),1);				// Home cursor same line as before
	}
#endif

#if LCD_ENABLE_CLEAR
void lcd_clear (void)							// Clear LCD screen
	{
	lcd_command (LCD_COMMAND_CLEAR);
	}
#endif

void lcd_init (void)							// Reset display from software
	{
	byte	i;
	
	LCD_E = 0;							// Set up control pin I/O
	LCD_TRIS_E = 0;
	LCD_RW = 0;							// Write mode
	LCD_TRIS_RW = 0;
	LCD_RS = 0;							// Command mode
	LCD_TRIS_RS = 0;

	LCD_TRIS_PORT &= ~LCD_TRIS_DATAMASK;				// Set data bus to output

	LCD_E = 0;							// Start talking to LCD
	delay_mS (15);							// Wait a little while

#if LCD_4_BIT_MODE							// Set LCD into 4-bit mode
	Lamp(10);
	lcd_putnybble (0b0011);						// Select 8-bit mode
	delay_mS (5);							// Spec calls for 4.1 mS
	lcd_putnybble (0b0011);						// Do it again
	delay_uS (100);
	lcd_putnybble (0b0011);
	lcd_putnybble (0b0010);						// Off and running...
#else
	lcd_putbyte (0b00110000);					// Select 8-bit mode
	delay_mS (5);							// Spec calls for 4.1 mS
	lcd_putbyte (0b00110000);					// Do it again
	delay_uS (100);
	lcd_putbyte (0b00110000);
	lcd_putbyte (0b00110000);					// Off and running...
#endif
	
	
	for (i = 0; i < sizeof(LCD_INIT_STRING); i++)			// Send other LCD initialization stuff
		lcd_command (LCD_INIT_STRING[i]);
	}

void Lamp(unsigned int n)
 {
 	for (int i=0;i<n;i++)
 	{
 		RA0=1;
 		delay_mS(1);
 		RA0=0;
 		delay_mS(1);
 	}
 }
can anyone help me???

many thanks
 

Attachments

csaba911

Member
I have not run ower your code, but noticed your test board running at 20Mhz, the lcd.c was writhed for "This is set up for 4 MHz oscillator".
The delay_mS (5) instruction is more like delay_mS (1).... 5x faster.


Csaba
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top